package dk.mirasola.systemtraining.user.server.service;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.ObjectifyService;
import dk.mirasola.systemtraining.server.entity.UserDistributionFilter;
import dk.mirasola.systemtraining.user.shared.service.UserDistributionFilterDataProviderService;
import dk.mirasola.systemtraining.user.shared.transfer.UserDistributionFilterTO;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Logger;

public class UserDistributionFilterDataProviderServiceImpl extends RemoteServiceServlet implements UserDistributionFilterDataProviderService {
    private static final Logger logger = Logger.getLogger(UserDistributionFilterDataProviderServiceImpl.class.getSimpleName());
    private static final int MAX_USER_DISTRIBUTION_FILTERS = 20;

    @Override
    public int[] initialData() {
        return new int[] {countUserDistributionFiltes(ObjectifyService.begin(),UserServiceFactory.getUserService().getCurrentUser()),MAX_USER_DISTRIBUTION_FILTERS};
    }

    private int countUserDistributionFiltes(Objectify ofy, User user) {
        return ofy.query(UserDistributionFilter.class)
                  .filter("owner", user)
                  .count();
    }

    @Override
    public List<UserDistributionFilterTO> getUserDistributionFilters(int firstResult, int maxResults) {
        Objectify ofy = ObjectifyService.begin();
        List<UserDistributionFilter> res =
                ofy.query(UserDistributionFilter.class)
                   .filter("owner", UserServiceFactory.getUserService().getCurrentUser())
                   .order("-id")
                   .offset(firstResult)
                   .limit(maxResults)
                   .list();
        return createUserDistributionFilterList(res,ofy.getFactory());
    }


    @Override
    public String createUserDistibutionFilter(UserDistributionFilterTO userDistributionFilterTO) {
        Objectify ofy = ObjectifyService.begin();
        User currentUser = UserServiceFactory.getUserService().getCurrentUser();

        if (countUserDistributionFiltes(ofy,currentUser) >= MAX_USER_DISTRIBUTION_FILTERS) {
            logger.warning("User " + currentUser.getEmail() + " tried to create more than allowed maximum distribution filters");
            throw new RuntimeException("Maximum distribution filters for user "+currentUser.getEmail()+" hit");
        }

        UserDistributionFilter filter = new UserDistributionFilter();
        filter.setOwner(currentUser);
        update(userDistributionFilterTO,ofy, filter);
        return ofy.getFactory().keyToString(ofy.getFactory().getKey(filter));
    }

    @Override
    public void deleteUserDistributionFilter(Set<String> userDistributionFilterIds) {
        Objectify ofy = ObjectifyService.begin();
        List<Key<?>> keys = new ArrayList<Key<?>>();
        for (String userDistributionFilterId : userDistributionFilterIds) {
            keys.add(ofy.getFactory().stringToKey(userDistributionFilterId));
        }
        ofy.delete(keys);
    }

    @Override
    public void updateUserDistributionFilter(UserDistributionFilterTO userDistributionFilter) {
        Objectify ofy = ObjectifyService.begin();
        Key<UserDistributionFilter> key = ofy.getFactory().stringToKey(userDistributionFilter.getId());
        UserDistributionFilter filter = ofy.get(key);
        update(userDistributionFilter, ofy, filter);
    }

    private void update(UserDistributionFilterTO userDistributionFilter, Objectify ofy, UserDistributionFilter filter) {
        filter.setName(userDistributionFilter.getName());
        filter.setDescription(userDistributionFilter.getDescription());
        filter.setDistributionFilterGroup(userDistributionFilter.getDistributionFilter());
        ofy.put(filter);
    }

    private List<UserDistributionFilterTO> createUserDistributionFilterList(List<UserDistributionFilter> userDistributionFilters,ObjectifyFactory factory) {
        List<UserDistributionFilterTO> res = new ArrayList<UserDistributionFilterTO>();
        for (UserDistributionFilter userDistributionFilter : userDistributionFilters) {
            res.add(createUserDistributionFilterTO(userDistributionFilter,factory));
        }
        return res;
    }

    private UserDistributionFilterTO createUserDistributionFilterTO(UserDistributionFilter userDistributionFilter,ObjectifyFactory factory) {
        UserDistributionFilterTO res = new UserDistributionFilterTO();
        res.setId(factory.keyToString(factory.getKey(userDistributionFilter)));
        res.setName(userDistributionFilter.getName());
        res.setDescription(userDistributionFilter.getDescription());
        res.setDistributionFilter(userDistributionFilter.getDistributionFilterGroup());
        return res;
    }

}

